<!DOCTYPE HTML>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>

<div class="container">
    <ul id="list1" role="listbox" aria-owns="item3">
        <li role="option">One</li>
        <li role="option">Two</li>
    </ul>
    <ul role="listbox" id="list2">
        <li role="option" id="item3">Three</li>
        <li role="option">Four</li>
    </ul>
</div>

<script>
test(function(t)
{
    const axList1 = accessibilityController.accessibleElementById("list1");
    assert_equals(axList1.role, "AXRole: AXListBox");
    assert_equals(axList1.childrenCount, 3);

    const axItem = axList1.childAtIndex(0);
    assert_equals(axList1.childAtIndex(0).name, "One");
    assert_equals(axList1.childAtIndex(1).name, "Two");
    assert_equals(axList1.childAtIndex(2).name, "Three");

    const axList2 = accessibilityController.accessibleElementById("list2");
    assert_equals(axList2.role, "AXRole: AXListBox");
    assert_equals(axList2.childrenCount, 1);
    assert_equals(axList2.childAtIndex(0).name, "Four");
}, "Aria-owns moves an element from one part of the tree to another.");
</script>

<div class="container">
    <ul id="parent1" role="listbox" aria-owns="child"></ul>
    <ul id="parent2" role="listbox" aria-owns="child"></ul>
    <ul id="parent3" role="listbox">
        <li id="child" role="option">Child</li>
    </ul>
</div>

<script>
test(function(t)
{
    const axParent1 = accessibilityController.accessibleElementById("parent1");
    const axParent2 = accessibilityController.accessibleElementById("parent2");
    const axParent3 = accessibilityController.accessibleElementById("parent3");
    const axChild = accessibilityController.accessibleElementById("child");

    // Either parent1 or parent2 should own the child, but either one is okay.
    const axActualParent = axChild.parentElement();
    assert_true(axActualParent.isEqual(axParent1) || axActualParent.isEqual(axParent2));
    if (axActualParent.isEqual(axParent1)) {
        assert_equals(axParent1.childrenCount, 1);
        assert_equals(axParent1.childAtIndex(0).name, "Child");
        assert_equals(axParent2.childrenCount, 0);
    } else {
        assert_equals(axParent1.childrenCount, 0);
        assert_equals(axParent2.childrenCount, 1);
        assert_equals(axParent2.childAtIndex(0).name, "Child");
    }
    assert_equals(axParent3.childrenCount, 0);
}, "If two nodes own (using aria-owns) the same element by id, only one gets to be the owner.");
</script>

<div class="container">
    <div id="xyz" role="group">
        <div id="x" role="group" aria-owns="y"></div>
        <div id="y" role="group" aria-owns="z"></div>
        <div id="z" role="group" aria-owns="x"></div>
    </div>
</div>

<script>
test(function(t)
{
    // Make sure we can walk the whole tree.
    accessibilityController.accessibleElementById("dummy");

    // Since there's no valid resolution to the cycle of aria-owns,
    // just assert that each element's parent is either its real parent
    // or its aria-owned parent, it doesn't matter which one.
    const axXYZ = accessibilityController.accessibleElementById("xyz");
    const axX = accessibilityController.accessibleElementById("x");
    const axY = accessibilityController.accessibleElementById("y");
    const axZ = accessibilityController.accessibleElementById("z");
    assert_true(axX.parentElement().isEqual(axXYZ) ||
                axX.parentElement().isEqual(axZ));
    assert_true(axY.parentElement().isEqual(axXYZ) ||
                axY.parentElement().isEqual(axX));
    assert_true(axZ.parentElement().isEqual(axXYZ) ||
                axZ.parentElement().isEqual(axY));
}, "An aria-owns relationship that would create a cycle is ignored.");
</script>

<div class="container">
    <div id="real-parent" role="group">
        <div id="owns-self" role="group" aria-owns="owns-self"></div>
    </div>
</div>

<script>
test(function(t)
{
    const axRealParent = accessibilityController.accessibleElementById("real-parent");
    const axOwnsSelf  = accessibilityController.accessibleElementById("owns-self");

    assert_true(axOwnsSelf.parentElement().isEqual(axRealParent));
    assert_equals(axOwnsSelf.childrenCount, 0);
}, "An element can't own itself.");
</script>

<div class="container">
    <div id="yancy" role="group">
        <div id="fry" role="group" aria-owns="yancy"></div>
    </div>
</div>

<script>
test(function(t)
{
    const axYancy = accessibilityController.accessibleElementById("yancy");
    const axFry = accessibilityController.accessibleElementById("fry");

    assert_equals(axFry.childrenCount, 0);
    assert_equals(axYancy.childrenCount, 1);
    assert_true(axYancy.childAtIndex(0).isEqual(axFry));
}, "An object cannot use aria-owns to own its own parent.");
</script>

<div class="container">
    <div id="logical_parent" role="group" aria-owns="logical_1 logical_2 logical_3 logical_4">
        <div id="logical_3">3</div>
        <div id="logical_4">4</div>
        <div id="logical_2">2</div>
        <div id="logical_1">1</div>
    </div>
</div>

<script>
test(function(t)
{
    const axLogicalParent = accessibilityController.accessibleElementById("logical_parent");

    assert_equals(axLogicalParent.childrenCount, 4);
    assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1");
    assert_equals(axLogicalParent.childAtIndex(1).childAtIndex(0).name, "2");
    assert_equals(axLogicalParent.childAtIndex(2).childAtIndex(0).name, "3");
    assert_equals(axLogicalParent.childAtIndex(3).childAtIndex(0).name, "4");
}, "A parent can use aria-owns to reorder its children into a more logical AX ordering.");
</script>

<div class="container">
    <ul id="dead_parent" aria-owns="orphan"></ul>
    <li id="orphan">Orphan</li>
</div>

<script>
test(function(t)
{
    const axDeadParent = accessibilityController.accessibleElementById(
        "dead_parent");
    assert_equals(axDeadParent.role, "AXRole: AXList");
    assert_equals(axDeadParent.childrenCount, 1);

    const axOrphan = axDeadParent.childAtIndex(0);
    assert_equals(axOrphan.role, "AXRole: AXListItem");
    assert_equals(axOrphan.parentElement().role, "AXRole: AXList");

    const deadParent = document.getElementById("dead_parent");
    deadParent.parentElement.removeChild(deadParent);

    const orphan = document.getElementById("orphan");
    orphan.setAttribute("id", "o2");
    orphan.setAttribute("id", "orphan");
}, "No crash if an aria-owns parent is deleted and the child is re-added.");
</script>
